#include <stdint.h>
#include <stdbool.h>
#include <glib.h>

#include "tvbuff.h"
#include "packet.h"
#include "proto.h"

#include "lua_dissect.h"
#include "lua_dissector.h"

/* 解析流程备忘
 * 1. 获取协议列表，得到协议名(short_name)
 * 2. 由协议名得到协议句柄
 * 3. 根据协议句柄判断协议是否使能
 * 4. 调用使能协议的解析方法
 * 5. 解析出错返回 -1，协议完全性检查失败返回 0，解析完返回数据长度
 * 6. ？需要添加完全性检查方法(integrity)吗？
 * 7. 根据(integrity)返回真值判断完全性还是交给(dissector)判断？
 */

lua_dissector_t *lua_dissect_new(void)
{
    lua_dissector_t *ldt;

    ldt = g_new0(lua_dissector_t, 1);

    lua_dissect_init(ldt);

    return ldt;
}

int lua_dissect_init(lua_dissector_t *ldt)
{
    memset(&ldt->pi, 0, sizeof(ldt->pi));
    ldt->tree = proto_tree_create_root(&ldt->pi);
    proto_tree_set_visible(ldt->tree, true);

    return 0;
}

int lua_dissect_run(lua_dissector_t *ldt, tvbuff_t *tvb)
{
    ldt->pi.proto_name = "<Missing Protocol Name>";
    ldt->pi.num = 0;
    
    ldt->tvb = tvb;
    
    add_new_data_source(&ldt->pi, ldt->tvb, "Frame");

    GList *dissector_names = get_dissector_names();

    if (dissector_names == NULL) return -1;

    for (GList *l = dissector_names; l != NULL; l = l->next) {
        dissector_handle_t handle = find_dissector((const char *)l->data);
        call_dissector(handle, ldt->tvb, &ldt->pi, ldt->tree);fflush(stdout);
    }
    
    return 0;
}

void lua_dissect_cleanup(lua_dissector_t *ldt)
{
    if (ldt == NULL) return;

    /* Free the data sources list. */
    free_data_sources(&ldt->pi);

    if (ldt->tvb) {
        /* Free all tvb's chained from this tvb */
        tvb_free_chain(ldt->tvb);
    }

    if (ldt->tree) {
        proto_tree_free(ldt->tree);
    }
}

void lua_dissect_free(lua_dissector_t *ldt)
{
    if (ldt == NULL) return;

    lua_dissect_cleanup(ldt);
    g_free(ldt);
}

